﻿

namespace BJYJ_Admin.Application.System.Services.User;
[ApiDescriptionSettings("System")]
public class SysRoleService : IDynamicApiController, ITransient
{

    public readonly ISqlSugarClient _db;
    public SysRoleService(ISqlSugarClient db)
    {
        _db = db;
    }
    /// <summary>
    /// 获取角色列表
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("获取角色列表")]
    public virtual async Task<PageResult<RoleListOutDto>> GetRoleList([FromQuery] RoleInfoSearchDto input)
    {
        RefAsync<int> totalCount = 0;
        var roleQuery = _db.Queryable<SYS_ROLE>()
            .WhereIF(!string.IsNullOrWhiteSpace(input.NAME), x => x.NAME.Contains(input.NAME))
            .WhereIF(input.PID.HasValue, x => x.PID == input.PID)
            .WhereIF(input.STATUS.HasValue, x => x.STATUS == input.STATUS)
            .WhereIF(input.DEPTH.HasValue, x => x.DEPTH == input.DEPTH)
            .OrderBy(x => x.PID, OrderByType.Asc)
            .OrderBy(x => x.ORDER_NUM, OrderByType.Asc)
            .Select(role => new RoleListOutDto
            {
                ID = role.ID,
                NAME = role.NAME,
                PID = role.PID,
                STATUS = role.STATUS,
                PARENT_PATH = role.PARENT_PATH,
                ORDER_NUM = role.ORDER_NUM,
                CODE = role.CODE,
                DEPTH = role.DEPTH,
                HASCHILDREN = false
            });


        // 执行分页查询
        var roleList = await roleQuery.ToPageListAsync(input.page, input.limit, totalCount);

        // 提取当前页所有角色ID
        var roleIds = roleList.Select(x => (int?)x.ID).ToList();

        // 批量查询哪些角色有子节点（使用聚合查询优化性能）
        var hasChildrenList = await _db.Queryable<SYS_ROLE>()
            .Where(x => roleIds.Contains(x.PID))
            .GroupBy(x => x.PID)
            .Select(x => new { PID = x.PID })
            .ToListAsync();

        // 创建快速查找字典
        var hasChildrenDict = hasChildrenList.ToDictionary(x => x.PID, x => true);

        // 给每个角色设置HasChildren属性
        foreach (var role in roleList)
        {
            role.HASCHILDREN = hasChildrenDict.ContainsKey(role.ID);
        }

        return new PageResult<RoleListOutDto>
        {
            page = input.page,
            limit = input.limit,
            totalcount = totalCount,
            data = roleList
        };
    }

    /// <summary>
    /// 新增角色
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("新增角色")]
    public virtual Task AddRole(RoleInfoInsertDto input)
    {
        var role = new SYS_ROLE
        {
            NAME = input.NAME,
            PID = input.PID,
            STATUS = input.STATUS,
            PARENT_PATH = input.PARENT_PATH,
            ORDER_NUM = input.ORDER_NUM,
            CODE = input.CODE,
            DEPTH = input.DEPTH,
            CREATE_BY = App.User?.FindFirstValue("ID"),
            CREATE_TIME = DateTime.Now
        };
        return _db.Insertable(role).ExecuteCommandAsync();
    }
    /// <summary>
    /// 更新角色
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("更新角色")]
    public virtual async Task UpdateRole(SYS_ROLE input)
    {
        input.UPDATE_TIME = DateTime.Now;
        input.UPDATE_BY = App.User?.FindFirstValue("ID");
        var result = await _db.Updateable(input)
                .IgnoreColumns(u => new { u.CREATE_BY, input.CREATE_TIME })
                .ExecuteCommandAsync();
        if (result == 0)
            throw Oops.Oh(ErrorCodeEnum.OP0002);
    }
    /// <summary>
    /// 删除角色
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("删除角色")]
    public virtual async Task DeleteRoleByID([FromQuery] RoleInfoIDDto input)
    {
        // 开启事务处理
        var result = await _db.Ado.UseTranAsync(async () =>
        {
            // 1.查询要删除角色的完整路径
            var role = await _db.Queryable<SYS_ROLE>().Where(x => x.ID == input.ID).FirstAsync();

            // 2.构建精确的路径匹配条件
            var currentMenuFullPath = $"{role.PARENT_PATH},{role.ID}";
            var pathPrefix = currentMenuFullPath + ",";  // 子角色路径前缀
            var directChildPath = currentMenuFullPath;   // 直接子节点路径

            // 3.查询要删除的子角色ID（精确匹配）
            var roleIds = await _db.Queryable<SYS_ROLE>()
                .Where(x => x.PARENT_PATH.StartsWith(pathPrefix)  // 所有后代
                    || x.PARENT_PATH == directChildPath)          // 直接子节点
                .Select(x => (int?)x.ID)
                .ToListAsync();

            // 4.加入当前角色ID
            roleIds.Add(input.ID);

            // 5. 删除角色角色关联
            await _db.Deleteable<SYS_ROLE_MENU>()
                   .Where(x => roleIds.Contains(x.MID))
                   .ExecuteCommandAsync();

            // 6. 删除子角色（使用相同的路径条件）
            await _db.Deleteable<SYS_ROLE>()
                .Where(x => x.PARENT_PATH.StartsWith(pathPrefix)
                    || x.PARENT_PATH == directChildPath)
                .ExecuteCommandAsync();
            // 7. 删除用户权限表的角色
            await _db.Deleteable<SYS_USER_ROLE>()
                    .Where(x => roleIds.Contains(x.RID))
                   .ExecuteCommandAsync();


            // 8. 删除当前角色
            await _db.Deleteable<SYS_ROLE>()
                .Where(x => x.ID == input.ID)
                .ExecuteCommandAsync();

        });
        if (!result.IsSuccess)
            throw Oops.Oh(result.ErrorMessage);

    }

    /// <summary>
    /// 角色详情
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("角色详情")]
    public virtual async Task<SYS_ROLE> GetRoleInfoByID(RoleInfoIDDto input)
    {
        var user = await _db.Queryable<SYS_ROLE>().Where(x => x.ID == input.ID).FirstAsync();
        return user;
    }

    /// <summary>
    /// 启用禁用角色
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("启用禁用角色")]
    public virtual async Task UpdateStatusByID(RoleStatusDto input)
    {
        var ID   = App.User?.FindFirstValue("ID");
        var result = await _db.Updateable<SYS_ROLE>()
                                   .SetColumns(it => it.STATUS == input.STATUS)
                                   .SetColumns(it => it.UPDATE_TIME == DateTime.Now)
                                   .SetColumns(it => it.UPDATE_BY == ID)
                                   .Where(it => it.ID == input.ID)
                                   .ExecuteCommandAsync();
        if (result == 0)
            throw Oops.Oh(ErrorCodeEnum.OP0000);
    }

    /// <summary>
    /// 给角色分配菜单
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("给角色分配菜单")]
    public virtual async Task SavePowerByRoleID(RolePowerDto input)
    {
        try
        {
            var ID   = App.User?.FindFirstValue("ID");
            var menus = input.MENUS?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            // 输入验证
            if (input.ROLEID <= 0)
                throw Oops.Oh($"无效的角色ID格式：{input.ROLEID}"); ;
            if (menus == null || menus.Length == 0)
                throw Oops.Oh($"无效的菜单ID格式：{input.MENUS}"); ;

            // 预验证菜单ID格式
            var menuIds = new List<int>();
            foreach (var menuIdStr in menus)
            {
                if (!int.TryParse(menuIdStr, out var menuId))
                {
                    throw Oops.Oh($"无效的菜单ID格式：{menuIdStr}");
                }
                menuIds.Add(menuId);
            }

            // 开启事务处理
            var result = await _db.Ado.UseTranAsync(async () =>
            {
                // 1. 删除旧权限
                await _db.Deleteable<SYS_ROLE_MENU>()
                       .Where(x => x.RID == input.ROLEID)
                       .ExecuteCommandAsync();

                // 2. 插入新权限
                var roleMenus = menuIds.Select(menuId => new SYS_ROLE_MENU
                {
                    RID = input.ROLEID,
                    MID = menuId,
                    CREATE_BY = ID,
                    CREATE_TIME = DateTime.Now
                }).ToList();
                await _db.Insertable(roleMenus).ExecuteCommandAsync();
            });

            if (!result.IsSuccess)
                throw Oops.Oh(result.ErrorMessage);
        }
        catch (Exception ex)
        {
            throw Oops.Oh(ex.Message);
        }

    }
    /// <summary>
    /// 获取指定角色的所有菜单
    /// </summary>
    /// <param name="id">角色id</param>
    /// <returns></returns>
    [DisplayName("获取指定角色的所有菜单")]
    public virtual async Task<List<int?>> GetMenuIDByRoleID(int id)
    {
        var roleMenus = await _db.Queryable<SYS_ROLE_MENU>()
            .Where(x => x.RID == id)
            .Select(x => x.MID)
            .ToListAsync();
        return roleMenus;
    }
    /// <summary>
    /// 给用户分配角色
    /// </summary>
    /// <param name="input"></param>
    /// <returns></returns>
    [DisplayName("给用户分配角色")]
    public virtual async Task SavePowerForUserByID(UserPowerDto input)
    {
        try
        {
            var UserName = App.User?.FindFirstValue("USERNAME");
            var roles = input.ROLES?.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);

            // 输入验证
            if (input.USERID <= 0)
                throw Oops.Oh($"无效的用户ID格式：{input.USERID}");
            if (roles == null || roles.Length == 0)
                throw Oops.Oh($"无效的角色ID格式：{input.USERID}");

            // 预验证菜单ID格式
            var menuIds = new List<int>();
            foreach (var menuIdStr in roles)
            {
                if (!int.TryParse(menuIdStr, out var menuId))
                {
                    throw Oops.Oh($"无效的角色ID格式：{menuIdStr}");
                }
                menuIds.Add(menuId);
            }

            // 开启事务处理
            var result = await _db.Ado.UseTranAsync(async () =>
            {
                // 1. 删除旧权限
                await _db.Deleteable<SYS_USER_ROLE>()
                       .Where(x => x.UID == input.USERID)
                       .ExecuteCommandAsync();

                // 2. 插入新权限
                var roleMenus = menuIds.Select(menuId => new SYS_USER_ROLE
                {
                    UID = input.USERID,
                    RID = menuId,
                }).ToList();
                await _db.Insertable(roleMenus).ExecuteCommandAsync();
            });
            if (!result.IsSuccess)
                throw Oops.Oh(result.ErrorMessage);
        }
        catch (Exception ex)
        {
            throw Oops.Oh(ex.Message);
        }

    }
    /// <summary>
    /// 获取用户的所有角色
    /// </summary>
    /// <param name="id">用户id</param>
    /// <returns></returns>
    [DisplayName("获取指定用户的所有角色")]
    public virtual async Task<List<int?>> GetRoleIDByUserID(int id)
    {
        var userRoles = await _db.Queryable<SYS_USER_ROLE>()
            .Where(x => x.UID == id)
            .Select(x => x.RID)
            .ToListAsync();
        return userRoles;
    }

}
